package io.renren.modules.task.wcs;

import com.sun.jna.WString;
import io.renren.common.utils.R;
import io.renren.modules.task.wcs.enums.IOServerEnum;
import ioserver.IOServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Vector;
import java.util.concurrent.Callable;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/12 15:28
 * @Version 1.0
 *
 * 这个类 是启动监听 是否堆垛机任务完成 和 给改变堆垛机plc 值（变相给堆垛机发任务）。
 * type = 0     // 发任务
 * type = 1 // 监听plc
 *
 *结果：
 *type = 0
 *      3 => 代表ioserver 写入异常； 1 代表 成功（两个成功）；  -1 代表其他错误
 *type = 1
 *      1 代表成功  ; 2 代表设备报错 ; -1 代表 失败（其他错误） ；
 *
 */
public class DDJRunnableCallable2<T> implements Callable<T> {
    private final static Logger logger = LoggerFactory.getLogger(DDJRunnableCallable2.class);
    private IOServerService ioServerService;
    private Integer type = -1;
    /**
     *当前层
     **/
    private com.ioserver.bean.Union_DataType.ByValue wscurrentLayer;
    /**
     *当前列（分为A、B）
     **/
    private com.ioserver.bean.Union_DataType.ByValue wscurrentColumn;
    /**
     *当前位置
     **/
    private com.ioserver.bean.Union_DataType.ByValue wscurrentPosition;
    /**
     *当前 堆垛机 是否在停止
     **/
    private com.ioserver.bean.Union_DataType.ByValue wswalkingRun;




    /**
     *  起点
     **/
    /**
     *目标层
     **/
    private String destinationLayer = null;
    /**
     *目标列
     **/
    private String destinationColumn = null;

    /**
     * 终点
     **/
    /**
     *取货位(一个位置 对应两列)
     **/
    private String takePosition = null;

    /**
     * 故障点
     **/

    private boolean wsWalking_Fault;
    private boolean wsLift_Fault;
    private boolean wsFork_Fault;
    private boolean wsConflict_Fault;


    /**
     * 优雅关闭
     **/
    private boolean switchs = true;


    public DDJRunnableCallable2(MyDDJArgEntity taskEntity, IOServerService ioServerService) {
        this.destinationLayer = taskEntity.getDestLayer();
        this.destinationColumn = taskEntity.getDestCol();
        this.takePosition = taskEntity.getTakePosition();
        this.ioServerService = ioServerService;
        this.type = taskEntity.getType();
    }

    @Override
    public synchronized T call() throws Exception {
        if(type == 0){
            //todo 给plc 写数据
            Integer integer = -1;
            Integer integer2 = -1;
            Integer integer3 = -1;
            try {
                integer = ioServerService.setTagValue(IOServerEnum.Target_Layer.getCollectionPointName(), destinationLayer, 1);
                integer2 = ioServerService.setTagValue(IOServerEnum.Target_Columns.getCollectionPointName(), destinationColumn, 1);
                integer3 = ioServerService.setTagValue(IOServerEnum.Take_Position.getCollectionPointName(), takePosition, 1);
            }catch (Exception e){
                logger.info("堆垛机IOServer 写入异常。");
                return (T)new Integer(3);
            }
            if(integer ==0 &&integer2 ==0 &&integer3 ==0){
                logger.info("IOServer 写入成功");
                return (T)new Integer(0);
            }else {
                logger.info("给IOServer 变量写数据异常。");
                return (T)new Integer(-1);
            }

            // 3 => 代表ioserver 写入异常； 1 代表 成功（两个成功）；
        }else {
            // 订阅所有变量
            Vector<WString> allTagName = ioServerService.getAllTagName();
            logger.info("所有变量："+allTagName);
            Integer flag = -1;
            //while (true && switchs){
            while (true){
                //logger.info("i am Listening");
                wswalkingRun = ioServerService.getValueByName(IOServerEnum.Walking_Run.getCollectionPointName());
                // 报错点
                wsWalking_Fault = ioServerService.getValueByName(IOServerEnum.Walking_Fault.getCollectionPointName()).bitVal;
                wsLift_Fault = ioServerService.getValueByName(IOServerEnum.Lift_Fault.getCollectionPointName()).bitVal;
                wsFork_Fault = ioServerService.getValueByName(IOServerEnum.Fork_Fault.getCollectionPointName()).bitVal;
                wsConflict_Fault = ioServerService.getValueByName(IOServerEnum.Conflict_Fault.getCollectionPointName()).bitVal;

                if(wsWalking_Fault || wsLift_Fault || wsFork_Fault || wsConflict_Fault ){
                    flag = 3;
                    break;
                }

                if(!wswalkingRun.bitVal){
                    //false 表示为 停止
                    try {
                        wscurrentLayer = ioServerService.getValueByName(IOServerEnum.Current_Layer.getCollectionPointName());
                        wscurrentColumn = ioServerService.getValueByName(IOServerEnum.Current_Column.getCollectionPointName());
                        wscurrentPosition = ioServerService.getValueByName(IOServerEnum.Current_Position.getCollectionPointName());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    if(wscurrentLayer.i2Val.equals(Short.valueOf(destinationLayer)) && wscurrentColumn.i2Val.equals(Short.valueOf(destinationColumn))){
                        //todo  放货成功后，写入日志（plc点表缺乏一个 完成任务成功的标志）
                        flag =1 ;
                        break;
                    }
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    logger.error("类名：DDJRunnableCallable<T>，线程名："+Thread.currentThread().getName()+"-线程意外退出了");
                    break;
                }
            }

            // -1 代表 失败（其他错误） ； 1 代表成功  ; 2 代表设备报错
            if(flag ==1 ){
                logger.info("堆垛机已近完成任务。");
                return (T) new Integer(1);
            }else if(flag == 3){
                logger.error("类名：DDJRunnableCallable<T>，165行代码，堆垛机设备出现故障。");
                return (T) new Integer(2);
            }else {
                logger.error("类名：DDJRunnableCallable<T>，168行代码，未知异常。");
                return (T) new Integer(-1);
            }
        }
    }

    public boolean isSwitchs() {
        return switchs;
    }

    public void setSwitchs(boolean switchs) {
        this.switchs = switchs;
    }

    public void shutdownGreaceful(){
        this.switchs = false;
    }

    public String getDestinationLayer() {
        return destinationLayer;
    }

    public void setDestinationLayer(String destinationLayer) {
        this.destinationLayer = destinationLayer;
    }

    public String getDestinationColumn() {
        return destinationColumn;
    }

    public void setDestinationColumn(String destinationColumn) {
        this.destinationColumn = destinationColumn;
    }

    public String getTakePosition() {
        return takePosition;
    }

    public void setTakePosition(String takePosition) {
        this.takePosition = takePosition;
    }


}
